// -----------------------------------------------------------------------
//  <copyright file="AuthorizationBehavior.cs" company="LiuliuSoft">
//      Copyright (c) 2022-2024 DaprPlus. All rights reserved.
//  </copyright>
//  <site>https://dapr.plus</site>
//  <last-editor>郭明锋</last-editor>
//  <last-date>2024/12/8 1:10:26</last-date>
// -----------------------------------------------------------------------

using DaprPlus.Authorization;


namespace DaprPlus.MediatR.Behaviors;

public class AuthorizationBehavior<TRequest, TResponse>(IServiceProvider provider) : IPipelineBehavior<TRequest, TResponse>
    where TRequest : IRequest<TResponse>
{
    public async Task<TResponse> Handle(TRequest request, RequestHandlerDelegate<TResponse> next, CancellationToken cancellationToken)
    {
        var attribute = typeof(TRequest).GetAttribute<AuthConfigAttribute>();
        if (attribute == null)
        {
            return await next();
        }

        var authConfig = attribute.ToAuthConfig();
        var cache = provider.GetRequiredService<IAuthorizationCache>();
        var resource = await cache.GetResourceCache(authConfig.ResourceCode, ResourceType.Entity);
        if (resource == null)
        {
            // todo: 多语言
            var msg = $"检查 {typeof(TRequest)} 权限时，资源 {authConfig.ResourceCode} 不存在";
            throw new AuthorizationException(new AuthorizationResult(AuthorizationStatus.Error, msg));
        }

        var authService = provider.GetRequiredKeyedService<IAuthorizationService>(ResourceType.Entity);
        var result = await authService.Authorize(resource, authConfig);
        if (!result.IsOk)
        {
            throw new AuthorizationException(result);
        }

        return await next();
    }
}
